#
#   pimento/command/put.rb - Pimento WebDAV client
#   	$Release Version: 0.0.1$
#   	$Revision: $
#   	$Date: $
#   	by Curl-Ojisan
#

require 'kconv'
require 'rexml/document'
require 'rexml/xpath'
require 'rexml/namespace'

# putコマンド: PUTリクエストを送る
class Pimento::Command::Put < Pimento::Command

  def initialize(local_filepath, remote_location)

    @local_filepath  = local_filepath
    @local_basename  = File.basename(@local_filepath)
    @remote_location = remote_location

    # ローカルファイルの状態を調べる
    @local_file_stat = File.stat(local_filepath)

    # リモートURIを解析
    @remote_uri = nil
    begin
      # PUT先の場所を解析
      @remote_uri = URI.parse(@remote_location)
    rescue
      # 解析に失敗したら例外を投げる
      raise 'Failed to parse remote location URI.'
    end

    # リモートURIのプロトコルをチェック
    if ! (@remote_uri.class <= URI::HTTP) then
      # 対応外プロトコルの場合例外を投げる
      raise 'Specified remote location URI protocol is not supported.'
    end

    # リモートURIにファイル名を連結
    begin
      # PUT先の場所とPUTするファイル名を連結して解析
      @remote_uri = @remote_uri + URI.escape(@local_basename.toutf8)
    rescue
      # 連結に失敗したら例外を投げる
      raise 'Failed to join file name to remote location URI.'
    end

  end

  def execute

    # リモートURIを一時変数に格納
    uri = @remote_uri

    remote_size = 0
    local_size  = 0

    # PUT先ファイルをPROPFINDして現状確認
    IO.popen("curl -K _curlrc -i -X PROPFIND #{uri.to_s}") {|io|

      # TODO: 'internal use only'なクラスを使っちゃってるのでなんとかしたい
      bio = Net::BufferedIO.new(io)
      res = Net::HTTPResponse.read_new(bio)

      Pimento.vp res

      # Not Found ならば、ファイルサイズは0のまま処理終了
      next if res.is_a? Net::HTTPNotFound

      # PROPFINDで返ってきたXML文書を解析
      res.reading_body(bio, true) { # body読込準備
          yield res if block_given?
      }
      Pimento.vputs body = res.body # body読込・デバッグ表示
      doc = REXML::Document.new(body) # body内容(XML)解析

      # リモートファイルのサイズを取得
      remote_size = REXML::XPath.first(
        doc, '//x:getcontentlength', {'x' => 'DAV:'}).text.to_i

    }
    local_size = @local_file_stat.size
    puts "Remote resource size:\t#{remote_size} bytes"
    puts "Local file size:\t#{local_size} bytes"
    # 最後まで完了していたら飛ばす
    if local_size <= remote_size
      puts 'Remote resource is larger than local file.  Nothing\'s to be done.'
      return
    end
    # 途中まで転送されていたら続きから
    # まだ転送されていなかったら最初から
    IO.popen("curl -K _curlrc -i -T #{@local_filepath} -C #{remote_size} #{@remote_location}") {|io|
      # TODO: 'internal use only'なクラスを使っちゃってるのでなんとかしたい
      bio = Net::BufferedIO.new(io)
      res = Net::HTTPResponse.read_new(bio)

      Pimento.vp res

      res.reading_body(bio, true) { # body読込準備
          yield res if block_given?
      }
      Pimento.vputs body = res.body
    }

  end

  def self.short_help
    'PUT a local file to a remote location'
  end

  def self.long_help
    'PUT a local file to a remote location'
  end

end # class Pimento::Command:Put

# vi: ts=8 sw=2 tw=80 fenc=utf-8
# END OF FILE
